package cn.ddiancan.xddcloud.common.security;

import java.security.SecureRandom;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.encrypt.TextEncryptor;

@Slf4j
public class AesService implements TextEncryptor {

    private static final String KEY_ALGORITHM = "AES";

    private static final String DEFAULT_CIPHER = "AES/CBC/PKCS5Padding";

    private static final byte[] ROOT_KEY = SecurityUtil.rootKey;

    private static final int IV_SIZE = 16;

    private static final String PREFIX = "{cipher}";

    public String encrypt(String content) {
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER);
            SecretKeySpec secretKeySpec = new SecretKeySpec(ROOT_KEY, KEY_ALGORITHM);
            IvParameterSpec ivParameterSpec = generateIv();
            byte[] iv = ivParameterSpec.getIV();
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] encrypted = cipher.doFinal(content.getBytes());
            // 将IV和密文一同返回，IV前面放置以便解密时使用
            byte[] encryptedIvAndText = new byte[iv.length + encrypted.length];
            System.arraycopy(iv, 0, encryptedIvAndText, 0, iv.length);
            System.arraycopy(encrypted, 0, encryptedIvAndText, iv.length, encrypted.length);

            // 返回Base64编码的结果
            return PREFIX + Base64.getEncoder().encodeToString(encryptedIvAndText);
        } catch (Exception e) {
            log.error("加密失败：{}", e.getMessage(), e);
        }
        return content;
    }

    public String decrypt(String encryptedContent) {
        try {
            if (encryptedContent.startsWith(PREFIX)) {
                encryptedContent = encryptedContent.substring(PREFIX.length());
            }
            SecretKeySpec secretKeySpec = new SecretKeySpec(ROOT_KEY, KEY_ALGORITHM);
            byte[] iv = new byte[IV_SIZE];
            byte[] encryptedIvAndText = Base64.getDecoder().decode(encryptedContent);
            byte[] encryptedBytes = new byte[encryptedIvAndText.length - iv.length];
            System.arraycopy(encryptedIvAndText, 0, iv, 0, iv.length);
            System.arraycopy(encryptedIvAndText, iv.length, encryptedBytes, 0, encryptedBytes.length);
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
            byte[] decrypted = cipher.doFinal(encryptedBytes);
            return new String(decrypted);
        } catch (Exception e) {
            log.error("解密失败：{}", e.getMessage(), e);
        }
        return encryptedContent;
    }

    // 生成一个初始化向量（IV），AES CBC模式需要IV
    private static IvParameterSpec generateIv() {
        byte[] iv = new byte[IV_SIZE]; // AES块大小为16字节
        new SecureRandom().nextBytes(iv);
        return new IvParameterSpec(iv);
    }
}
